<?php
class pdoSqlite_easy extends Db{

	private static $ins=null;
	private $cfg=array();
	private $link=null;
	private $stmt=null;
	private $error_code=0;
	private $error_info='';

	protected function __construct() {
		if(!class_exists('PDO')) exit('PDO未开启'); 
		$this->need_comma=false;
		$this->addslashes=false;
		$this->cfg=VG::$config;
		$this->dbprefix=VG::$db['dbprefix'];
		$this->connect();
	}
	public function __destruct(){
		$this->close();
	}
	public function setTableAddon($tabName){
		$cachefile=APPPATH.'runtime/table_cache/'.$tabName.'.addon.php';
		$auto=0;
		if(file_exists($cachefile)){
			//add
			if(defined('DEBUG') and DEBUG==TRUE){
				$result=$this->query("pragma table_info ('{$tabName}')");
				$_fields=array();
				$fields=array();
				while($row=$this->fetch_assoc($result)){
					$_fields[]=$row['name'];
					if($row['pk']==1){
						$fields['pk']=$row['name'];
					}
				}
				if(!array_key_exists('pk', $fields)){
					$fields['pk']=$_fields[0];		
				}
				$fields['auto']=$auto;
				$this->free_result($result);
				return $fields;
			}
			//add
			return include($cachefile);
		}else{
			$result=$this->query("pragma table_info ('{$tabName}')");
			$_fields=array();
			$fields=array();
			while($row=$this->fetch_assoc($result)){
				$_fields[]=$row['name'];
				if($row['pk']==1){
					$fields['pk']=$row['name'];
				}
			}
			if(!array_key_exists('pk', $fields)){
				$fields['pk']=$_fields[0];		
			}
			$fields['auto']=$auto;
			$this->free_result($result);
			
			$str="<?php\r\n";
			$str.='return ';
			$str.=var_export($fields,true);
			$str.=';';
			$r=file_put_contents($cachefile, $str);
			if(!$r) exit('table_cache failed!');
			return $fields;
		}
	}
	public function setTable($tabName){
		$cachefile=APPPATH.'runtime/table_cache/'.$tabName.'.php';
		if(file_exists($cachefile)){
			//add
			if(defined('DEBUG') and DEBUG==TRUE){
				$result=$this->query("pragma table_info ('{$tabName}')");
				$fields=array();
				while($row=$this->fetch_assoc($result)){
					$fields[]=$row['name'];
				}
				$this->free_result($result);
				return $fields;
			}
			//add
			return include($cachefile);
		}else{
			$result=$this->query("pragma table_info ('{$tabName}')");
			$fields=array();
			while($row=$this->fetch_assoc($result)){
				$fields[]=$row['name'];
			}
			$this->free_result($result);
			
			$str="<?php\r\n";
			$str.='return ';
			$str.=var_export($fields,true);
			$str.=';';
			$r=file_put_contents($cachefile, $str);
			if(!$r) exit('table_cache failed!');
			return $fields;
		}
	}
	public static function getIns() {
        if(!(self::$ins instanceof self)) {
            self::$ins=new self();
        }
        return self::$ins;
	}
	public function getLink(){
		return $this->link;
	}
	//sqlite:e:/a.db
	protected function connect(){
		$config_db=VG::$db;
		if(!isset($config_db['dsn'])) exit('db need dsn param!');
		try{
			$this->link=new PDO($config_db['dsn'],$config_db['username'],$config_db['password']);
			$this->link->setAttribute(PDO::ATTR_ERRMODE,  PDO::ERRMODE_EXCEPTION);
			$this->link->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY,  true);
			
		}catch(PDOException $e){
			echo "数据库连接失败：".$e->getMessage();
			exit;
		}
	}
	public function colligate_query($sql, $method,$data=array()){
		 $marr=explode("::", $method);
		 $method=strtolower(array_pop($marr));
		 if(strtolower($method)=='total'){
			$sql=preg_replace('/select.*?from/i','SELECT count(*) as count FROM',$sql);
		 }
		 try{
			$this->rec_sql($sql);
			$this->last_sql=$sql;
			$return=null;
			$this->stmt=$stmt=$this->link->prepare($sql);  //准备好一个语句
			$result=$stmt->execute($data);   //执行一个准备好的语句
			
			 switch($method){
				 case "easy_select":  //查所有满足条件的
					 $data=$stmt->fetchAll(PDO::FETCH_ASSOC);
					 $return=$data;
					break;
				case "easy_find":    //只要一条记录的
					$data=$stmt->fetch(PDO::FETCH_ASSOC);
					$return=$data;
					break;
				case "easy_total":  //返回总记录数
					$row=$stmt->fetch(PDO::FETCH_NUM);
					$return=$row[0];
					break;
				case "easy_insert":  //插入数据 返回最后插入的ID
					$return=$this->link->lastInsertId();
					break;
				case "easy_delete":
				case "easy_update":        //update 
					//$return=$stmt->rowCount();//?
					$return=$result;
					break;
				default:
					$return=$result;
			 }
			return $return;
		}catch(PDOException $e){
			if($msg=$this->err(1)){
				$pos=$_SESSION['_debug_pos_'];
				$this->_log_err($pos.$msg.$sql.serialize($data).'\n');
				unset($_SESSION['_debug_pos_']);
			}
			exit($sql.'||||'.$e->getMessage());
		}	
	}
	private function __clone(){
	}
	public function close(){
		$this->link=null;
	}
	public function exec($query,$data=array()){
		try{
			$query=$this->replace_tablename($query);
			$r=$this->link->exec($query);
			$this->rec_sql($query);
			$this->last_sql=$query;
		}catch(PDOException $e){
			if($msg=$this->err(0)){
				$pos=$_SESSION['_debug_pos_'];
				$this->_log_err($pos.$msg.$query.'\n');
				unset($_SESSION['_debug_pos_']);
			}
			exit($query.'||||'.$e->getMessage());
		}	
		return $r;
	}
	protected function parse_sql($sql,$data=array()){
		//$data=stripslashes_array($data);//去除反斜线
		try{
			$stmt=$this->link->prepare($sql);
			$this->stmt=$stmt;
			$r=$stmt->execute($data);
		}catch(PDOException $e){
			if($msg=$this->err(1)){
				$pos=$_SESSION['_debug_pos_'];
				$this->_log_err($pos.$msg.$sql.serialize($data).'\n');
				unset($_SESSION['_debug_pos_']);
			}
			exit($sql.'||||'.$e->getMessage());
		}	
		return $r;
	}
	//需要prepare 需要绑定数据 有stmt
	public function query($query,$data=array()){
		$query=$this->replace_tablename($query);
		$r=$this->parse_sql($query,$data);
		$this->rec_sql($query);
		$this->last_sql=$query;
		return $r;
	}
	public function err(){
		$is_statement=func_get_arg(0);
		if($is_statement){
			$this->error_code=$this->stmt->errorCode();
			$this->error_info=implode(' ',$this->stmt->errorInfo());
		}else{
			$this->error_code=$this->link->errorCode();
			$this->error_info=implode(' ',$this->link->errorInfo());
		}
		if($this->error_code>0){
			return $this->error_code.':'.$this->error_info;
		}else{
			return false;
		}
	}
	//
	public function fetch_array($result,$type){
		switch($type){
			case 'ASSOC':
				return $this->stmt->fetch(PDO::FETCH_ASSOC);
			break;
			case 'NUM':
				return $this->stmt->fetch(PDO::FETCH_NUM);
			break;
			case 'BOTH':
				return $this->stmt->fetch(PDO::FETCH_BOTH);
			break;
			default:
				return $this->stmt->fetch(PDO::FETCH_ASSOC);
			break;
		}
	}
	public function fetch_array_all($result,$type){
		switch($type){
			case 'ASSOC':
				return $this->stmt->fetchAll(PDO::FETCH_ASSOC);
			break;
			case 'NUM':
				return $this->stmt->fetchAll(PDO::FETCH_NUM);
			break;
			case 'BOTH':
				return $this->stmt->fetchAll(PDO::FETCH_BOTH);
			break;
			default:
				return $this->stmt->fetchAll(PDO::FETCH_ASSOC);
			break;
		}
	}
	public function fetch_row($result){
		return $this->stmt->fetch(PDO::FETCH_NUM);
	}
	public function fetch_assoc($result){
		return $this->stmt->fetch(PDO::FETCH_ASSOC);
	}
	public function affected_rows(){
		return $this->stmt->rowCount();
	}

	public function beginTransaction() {
		$this->link->setAttribute(PDO::ATTR_AUTOCOMMIT, 0); 
		$this->link->beginTransaction();
	}
	public function commit() {
		$this->link->commit();
		$this->link->setAttribute(PDO::ATTR_AUTOCOMMIT, 1); 
	}
	public function rollBack() {
		$this->link->rollBack();
		$this->link->setAttribute(PDO::ATTR_AUTOCOMMIT, 1); 
	}
	public function dbVersion() {
		return $this->link->getAttribute(PDO::ATTR_SERVER_VERSION);
	}
	public function dbSize() {
		return 0;
	}
	public function free_result($result) {
		return true;
	}
	public function insert_id() {
		return $this->link->lastInsertId();
	}
	private function _replace($string){
		if(is_array($string)) { 
			foreach($string as $key => $val) { 
				$string[$key] = $this->_replace($val); 
			} 
		} else { 
			$search=array(
				"/",
				"'",
				"[",
				"]",
				"%",
				"&",
				"_",
				"(",
				")",
			);
			$replace=array(
				"//",
				"''",
				"/[",
				"/]",
				"/%",
				"/&",
				"/_",
				"/(",
				"/)",
			);
			$string=str_replace($search,$replace,$string);
		} 
		return $string;
	}
	public function escape($d){
		if(!GPC){
		
		}else{
			$d=stripslashes_array($d);
		}
		return $this->_replace($d);
	}
}
